package com.jk.common.oss;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import static com.jk.common.utils.FileUtil.getInputStreamFromUrl;


@Slf4j
@Service
public class OssClient {
    @Autowired
    private OssProperties ossProperties;


    /**
     * MultipartFile 转存阿里云
     */
    public String uploadFile(String fileName, MultipartFile file) {
        OSS ossClient = new OSSClientBuilder().build(
                ossProperties.getEndpoint(),
                ossProperties.getAccessKeyId(),
                ossProperties.getAccessKeySecret()
        );
        try {
            ossClient.putObject(ossProperties.getBucketName(), fileName, file.getInputStream());
            String url = ossProperties.getUrl() + "/" + fileName;
            log.info("OSS上传成功，文件地址：{}", url);
            return url;
        } catch (Exception e) {
            log.error("OSS文件上传失败！失败原因:", e);
        } finally {
            ossClient.shutdown();
        }
        return null;
    }


    /**
     * 获取 上传下载凭证
     */
    public Map<String, String> getUploadCredentials(String prefix) throws Exception {
        OSS ossClient = new OSSClientBuilder().build(
                ossProperties.getEndpoint(),
                ossProperties.getRamAccessKeyId(),
                ossProperties.getRamAccessKeySecret()
        );
        Map<String, String> responseMap = new HashMap<>();
        try {
            long expireEndTime = System.currentTimeMillis() + 3600 * 24 * 1000;
            Date expiration = new Date(expireEndTime);
            PolicyConditions policyConds = new PolicyConditions();
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
            policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, prefix);
            String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
            byte[] binaryData = postPolicy.getBytes(StandardCharsets.UTF_8);
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            String postSignature = ossClient.calculatePostSignature(postPolicy);
            responseMap.put("ossAccessKeyId", ossProperties.getRamAccessKeyId());
            responseMap.put("policy", encodedPolicy);
            responseMap.put("signature", postSignature);
            responseMap.put("dir", prefix);
            responseMap.put("host", ossProperties.getUrl());
        } catch (OSSException | ClientException oe) {
            throw new Exception(oe);
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return responseMap;
    }



    /**
     * 文件流式转存阿里云
     */
    public String uploadFile(String fileName, InputStream inputStream) {
        OSS ossClient = new OSSClientBuilder().build(
                ossProperties.getEndpoint(),
                ossProperties.getAccessKeyId(),
                ossProperties.getAccessKeySecret()
        );
        try {
            ossClient.putObject(ossProperties.getBucketName(), fileName, inputStream);
            return ossProperties.getUrl() + "/" + fileName;
        } catch (Exception e) {
            log.error("OSS文件上传失败！失败原因:", e);
        } finally {
            ossClient.shutdown();
        }
        return null;
    }

    /**
     * 文件url转存阿里云 -最终还是流式
     */
    public String uploadFile(String fileName, String imageUrl) {
        try {
            // 下载图片的输入流
            InputStream inputStream = getInputStreamFromUrl(imageUrl);
            if (inputStream != null) {
                return this.uploadFile(fileName, inputStream);
            }
        } catch (Exception e) {
            log.error("OSS文件上传失败！失败原因:", e);
        }
        return null;
    }

}